<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
<!-- rasterwindow.qdoc -->
  <title>Raster Window 例子 | Qt GUI 5.14.2</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td ><a href="../qtdoc/index.html">Qt 5.14</a></td><td ><a href="qtgui-index.html">Qt GUI</a></td><td >Raster Window 例子</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right"><a href="qtgui-index.html">Qt 5.14.2 参考文档</a></td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
<div class="sidebar">
<div class="toc">
<h3><a name="toc">目录</a></h3>
<ul>
<li class="level1"><a href="#application-entry-point">应用程序入口点</a></li>
<li class="level1"><a href="#rasterwindow-declaration">RasterWindow 声明</a></li>
<li class="level1"><a href="#rasterwindow-implementation">RasterWindow 实现</a></li>
<li class="level1"><a href="#rendering-asynchronously">异步渲染</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">Raster Window 例子</h1>
<span class="subtitle"></span>
<!-- $$$rasterwindow-brief -->
<p>这个例子展示了如何使用 <a href="qpainter.html">QPainter</a> 创建一个最小的基于 <a href="qwindow.html">QWindow</a> 的应用程序 。</p>
<!-- @@@rasterwindow -->
<!-- $$$rasterwindow-description -->
<div class="descr"> <a name="details"></a>
<a name="application-entry-point"></a>
<h4 id="application-entry-point">应用程序入口点</h4>
<pre class="cpp">

  <span class="type">int</span> main(<span class="type">int</span> argc<span class="operator">,</span> <span class="type">char</span> <span class="operator">*</span><span class="operator">*</span>argv)
  {
      <span class="type"><a href="qguiapplication.html">QGuiApplication</a></span> app(argc<span class="operator">,</span> argv);

      RasterWindow window;
      window<span class="operator">.</span>show();

      <span class="keyword">return</span> app<span class="operator">.</span>exec();
  }

</pre>
<p>基于 <a href="qwindow.html">QWindow</a> 的应用程序的入口点是 <a href="qguiapplication.html">QGuiApplication</a> 类 。它管理GUI应用程序的控制流和主要设置 。我们传递命令行参数，这些参数可用于获取某些系统范围的选项 。</p>
<p>从那里，我们继续创建我们的窗口实例，然后调用 <a href="qwindow.html#show">QWindow::show</a>()函数来告诉窗口系统这个窗口现在应该在屏幕上可见 。</p>
<p>完成此操作后，我们进入应用程序的事件循环，以便应用程序可以运行 。</p>
<a name="rasterwindow-declaration"></a>
<h4 id="rasterwindow-declaration">RasterWindow 声明</h4>
<pre class="cpp">

  <span class="preprocessor">#include &lt;QtGui&gt;</span>

  <span class="keyword">class</span> RasterWindow : <span class="keyword">public</span> <span class="type"><a href="qwindow.html">QWindow</a></span>
  {
      Q_OBJECT
  <span class="keyword">public</span>:
      <span class="keyword">explicit</span> RasterWindow(<span class="type"><a href="qwindow.html">QWindow</a></span> <span class="operator">*</span>parent <span class="operator">=</span> <span class="number">0</span>);

      <span class="keyword">virtual</span> <span class="type">void</span> render(<span class="type"><a href="qpainter.html">QPainter</a></span> <span class="operator">*</span>painter);

  <span class="keyword">public</span> <span class="keyword">slots</span>:
      <span class="type">void</span> renderLater();
      <span class="type">void</span> renderNow();

  <span class="keyword">protected</span>:
      bool event(<span class="type"><a href="../qtcore/qevent.html">QEvent</a></span> <span class="operator">*</span>event) override;

      <span class="type">void</span> resizeEvent(<span class="type"><a href="qresizeevent.html">QResizeEvent</a></span> <span class="operator">*</span>event) override;
      <span class="type">void</span> exposeEvent(<span class="type"><a href="qexposeevent.html">QExposeEvent</a></span> <span class="operator">*</span>event) override;

  <span class="keyword">private</span>:
      <span class="type"><a href="qbackingstore.html">QBackingStore</a></span> <span class="operator">*</span>m_backingStore;
  };

</pre>
<p>我们首先包含 <code>&lt;QtGui&gt;</code> 头文件。这意味着我们可以使用Qt GUI模块中的所有类。如果喜欢的话，类也可以单独包含 。</p>
<p>RasterWindow类直接子类化了 <a href="qwindow.html">QWindow</a> ，并提供了一个构造函数，它允许窗口成为另一个 <a href="qwindow.html">QWindow</a> 的子窗口。无父窗口的qwindow在窗口系统中显示为顶级窗口 。</p>
<p>这个类声明了一个 <a href="qbackingstore.html">QBackingStore</a> ，我们用它来管理基于 <a href="qpainter.html">QPainter</a> 图形的窗口后台缓存 。</p>
<p><i> raster window 也在其他一些例子中被重用，并添加了一些辅助函数，如 renderLater() 。</i></p>
<a name="rasterwindow-implementation"></a>
<h4 id="rasterwindow-implementation">RasterWindow 实现</h4>
<pre class="cpp">

  RasterWindow<span class="operator">::</span>RasterWindow(<span class="type"><a href="qwindow.html">QWindow</a></span> <span class="operator">*</span>parent)
      : <span class="type"><a href="qwindow.html">QWindow</a></span>(parent)
      <span class="operator">,</span> m_backingStore(<span class="keyword">new</span> <span class="type"><a href="qbackingstore.html">QBackingStore</a></span>(<span class="keyword">this</span>))
  {
      setGeometry(<span class="number">100</span><span class="operator">,</span> <span class="number">100</span><span class="operator">,</span> <span class="number">300</span><span class="operator">,</span> <span class="number">200</span>);
  }

</pre>
<p>在构造函数中，我们创建 backingstore，并将它应该管理的窗口实例传递给它 。我们还设置了初始窗口的几何形状 。</p>
<pre class="cpp">

  <span class="type">void</span> RasterWindow<span class="operator">::</span>exposeEvent(<span class="type"><a href="qexposeevent.html">QExposeEvent</a></span> <span class="operator">*</span>)
  {
      <span class="keyword">if</span> (isExposed())
          renderNow();
  }

</pre>
<p>在对一个创建的窗口调用 <a href="qwindow.html#show">QWindow::show</a>() 后不久，虚函数 <a href="qwindow.html#exposeEvent">QWindow::exposeEvent</a>() 将被调用，以通知我们窗口在窗口系统中的曝光已经改变 。事件包含公开的子区域，但是由于我们每次都会绘制整个窗口，所以我们没有使用它 。</p>
<p>函数 <a href="qwindow.html#isExposed">QWindow::isExposed</a>() 将告诉我们窗口是否显示 。我们需要这个，因为当窗口在窗口系统中变得模糊时，exposeEvent也被调用 。如果窗口显示，我们调用renderNow()立即绘制窗口 。我们想要立即绘制，这样我们就可以为系统渲染一些可视内容 。</p>
<pre class="cpp">

  <span class="type">void</span> RasterWindow<span class="operator">::</span>resizeEvent(<span class="type"><a href="qresizeevent.html">QResizeEvent</a></span> <span class="operator">*</span>resizeEvent)
  {
      m_backingStore<span class="operator">-</span><span class="operator">&gt;</span>resize(resizeEvent<span class="operator">-</span><span class="operator">&gt;</span>size());
  }

</pre>
<p>resize 事件保证在窗口显示在屏幕上之前被调用，当窗口在屏幕上被调整大小时也会被调用 。我们使用它来调整后台缓冲区的大小，并将显示延迟到相应的/随后的 expose 事件 。</p>
<pre class="cpp">

  <span class="type">void</span> RasterWindow<span class="operator">::</span>renderNow()
  {
      <span class="keyword">if</span> (<span class="operator">!</span>isExposed())
          <span class="keyword">return</span>;

      <span class="type"><a href="../qtcore/qrect.html">QRect</a></span> rect(<span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> width()<span class="operator">,</span> height());
      m_backingStore<span class="operator">-</span><span class="operator">&gt;</span>beginPaint(rect);

      <span class="type"><a href="qpaintdevice.html">QPaintDevice</a></span> <span class="operator">*</span>device <span class="operator">=</span> m_backingStore<span class="operator">-</span><span class="operator">&gt;</span>paintDevice();
      <span class="type"><a href="qpainter.html">QPainter</a></span> painter(device);

      painter<span class="operator">.</span>fillRect(<span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> width()<span class="operator">,</span> height()<span class="operator">,</span> <span class="type"><a href="qgradient.html">QGradient</a></span><span class="operator">::</span>NightFade);
      render(<span class="operator">&amp;</span>painter);
      painter<span class="operator">.</span>end();

      m_backingStore<span class="operator">-</span><span class="operator">&gt;</span>endPaint();
      m_backingStore<span class="operator">-</span><span class="operator">&gt;</span>flush(rect);
  }

</pre>
<p>renderNow函数设置 <a href="qwindow.html">QWindow</a> 使用 <a href="qpainter.html">QPainter</a> 渲染它的内容所需要的内容 。由于模糊的窗口将不可见，如果窗口在窗口系统中未暴露，我们将终止 。例如，当另一个窗口完全掩盖了该窗口时，就会发生这种情况 。</p>
<p>我们通过调用 <a href="qbackingstore.html#beginPaint">QBackingStore::beginPaint</a>() 在我们想要绘制的区域开始绘制 。然后，我们获得后台缓冲区的 <a href="qpaintdevice.html">QPaintDevice</a> ，并创建一个 <a href="qpainter.html">QPainter</a> 来渲染那个绘制设备 。</p>
<p>为了消除上次渲染留下的痕迹，从一个干净的缓冲区开始，我们用白色填充整个缓冲区 。然后我们调用 virtual render() 函数来绘制这个窗口 。</p>
<p>绘制完成后，我们调用 endPaint() 来表示我们已经完成了渲染，并使用 <a href="qbackingstore.html#flush">QBackingStore::flush</a>() 在后台缓冲区中显示内容 。</p>
<pre class="cpp">

  <span class="type">void</span> RasterWindow<span class="operator">::</span>render(<span class="type"><a href="qpainter.html">QPainter</a></span> <span class="operator">*</span>painter)
  {
      painter<span class="operator">-</span><span class="operator">&gt;</span>drawText(<span class="type"><a href="../qtcore/qrectf.html">QRectF</a></span>(<span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> width()<span class="operator">,</span> height())<span class="operator">,</span> <span class="type"><a href="qt-sub-qtgui.html">Qt</a></span><span class="operator">::</span>AlignCenter<span class="operator">,</span> <span class="type"><a href="../qtcore/qstring.html#QStringLiteral">QStringLiteral</a></span>(<span class="string">&quot;QWindow&quot;</span>));
  }

</pre>
<p>render 函数包含窗口的绘图代码 。在这个简单的例子中，我们只在中间绘制字符串 &quot;<a href="qwindow.html">QWindow</a> &quot; 。</p>
<a name="rendering-asynchronously"></a>
<h4 id="rendering-asynchronously">异步渲染</h4>
<pre class="cpp">

  <span class="type">void</span> RasterWindow<span class="operator">::</span>renderLater()
  {
      requestUpdate();
  }

</pre>
<p>有几个地方的窗户需要立即重新绘制 。在某些情况下，这是不可取的，而是让应用程序返回事件循环并安排稍后重新绘制 。我们通过使用 <a href="qwindow.html#requestUpdate">QWindow::requestUpdate</a>() 请求更新来实现这一点，当系统准备好重绘时，它将被提交 。</p>
<pre class="cpp">

  bool RasterWindow<span class="operator">::</span>event(<span class="type"><a href="../qtcore/qevent.html">QEvent</a></span> <span class="operator">*</span>event)
  {
      <span class="keyword">if</span> (event<span class="operator">-</span><span class="operator">&gt;</span>type() <span class="operator">=</span><span class="operator">=</span> <span class="type"><a href="../qtcore/qevent.html">QEvent</a></span><span class="operator">::</span>UpdateRequest) {
          renderNow();
          <span class="keyword">return</span> <span class="keyword">true</span>;
      }
      <span class="keyword">return</span> <span class="type"><a href="qwindow.html">QWindow</a></span><span class="operator">::</span>event(event);
  }

</pre>
<p>我们重新实现virtual <a href="../qtcore/qobject.html#event">QObject::event</a>() 函数来处理更新事件 。当事件进来时，我们调用 renderNow() 来立即渲染窗口 。</p>
<p><a href="https://code.qt.io/cgit/qt/qtbase.git/tree/examples/gui/rasterwindow?h=5.14">Example project @ code.qt.io</a></p>
</div>
<!-- @@@rasterwindow -->
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2020 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br/>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br/>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>
